package com.lingnan.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.lingnan.entity.NotificationDTO;
import com.lingnan.entity.NotificationEntity;
import com.lingnan.entity.NotificationReceiverEntity;
import com.lingnan.entity.dto.BatchNotificationDTO;
import com.lingnan.mapper.NotificationMapper;
import com.lingnan.mapper.NotificationReceiverMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

// NotificationService.java
@Service
@Slf4j
public class NotificationService {
    
    @Autowired
    private NotificationMapper notificationMapper;
    
    @Autowired
    private NotificationReceiverMapper receiverMapper;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    @Value("${notification.exchange}")
    private String notificationExchange;
    
    @Value("${notification.routing-key}")
    private String notificationRoutingKey;
    
    private static final String UNREAD_COUNT_KEY = "notification:unread:";

    /**
     * 批量发送通知
     */
    @Transactional
    public void batchSendNotification(BatchNotificationDTO batchDTO) {
        try {
            if (batchDTO.getReceiverType() == 2) {
                // 发送系统公告给全体用户
                sendSystemAnnouncement(batchDTO.getSenderId(), batchDTO.getTitle(), batchDTO.getContent());
            } else {
                // 批量发送个人通知
                List<NotificationEntity> notifications = new ArrayList<>();

                for (Long receiverId : batchDTO.getReceiverIds()) {
                    NotificationEntity notification = new NotificationEntity();
                    notification.setSenderId(batchDTO.getSenderId());
                    notification.setReceiverId(receiverId);
                    notification.setReceiverType(0); // 个人通知
                    notification.setTitle(batchDTO.getTitle());
                    notification.setContent(batchDTO.getContent());
                    notification.setType(batchDTO.getType());
                    notification.setStatus(0);
                    notification.setCreatedAt(new Date());

                    notifications.add(notification);
                }

                // 批量插入数据库
                batchInsertNotifications(notifications);

                // 批量更新Redis未读计数
                batchUpdateUnreadCount(batchDTO.getReceiverIds());

                // 批量发送到消息队列
                batchPublishNotifications(notifications);

                log.info("批量发送通知成功，接收者数量: {}", batchDTO.getReceiverIds().size());
            }
        } catch (Exception e) {
            log.error("批量发送通知失败", e);
            throw new RuntimeException("批量发送通知失败", e);
        }
    }

    /**
     * 批量发送通知（重载方法 - 接收NotificationDTO列表）
     */
    @Transactional
    public void batchSendNotification(List<NotificationDTO> notifications) {
        try {
            List<NotificationEntity> entities = new ArrayList<>();
            List<Long> receiverIds = new ArrayList<>();

            for (NotificationDTO dto : notifications) {
                NotificationEntity entity = new NotificationEntity();
                entity.setSenderId(dto.getSenderId());
                entity.setReceiverId(dto.getReceiverId());
                entity.setReceiverType(dto.getReceiverType() != null ? dto.getReceiverType() : 0);
                entity.setTitle(dto.getTitle());
                entity.setContent(dto.getContent());
                entity.setType(dto.getType());
                entity.setStatus(0);
                entity.setCreatedAt(new Date());

                entities.add(entity);
                receiverIds.add(dto.getReceiverId());
            }

            // 批量插入数据库
            batchInsertNotifications(entities);

            // 批量更新Redis未读计数
            batchUpdateUnreadCount(receiverIds);

            // 批量发送到消息队列
            batchPublishNotifications(entities);

            log.info("批量发送通知成功，通知数量: {}", notifications.size());
        } catch (Exception e) {
            log.error("批量发送通知失败", e);
            throw new RuntimeException("批量发送通知失败", e);
        }
    }

    /**
     * 批量插入通知到数据库
     */
    private void batchInsertNotifications(List<NotificationEntity> notifications) {
        if (!notifications.isEmpty()) {
            notificationMapper.batchInsert(notifications);
        }
    }

    /**
     * 批量更新Redis未读计数
     */
    private void batchUpdateUnreadCount(List<Long> userIds) {
        for (Long userId : userIds) {
            updateUnreadCount(userId);
        }
    }

    /**
     * 批量发布通知到消息队列
     */
    private void batchPublishNotifications(List<NotificationEntity> notifications) {
        for (NotificationEntity notification : notifications) {
            publishNotification(notification);
        }
    }
    
    /**
     * 发送个人通知
     */
    public void sendPersonalNotification(Long senderId, Long receiverId, String title, String content, Integer type) {
        NotificationEntity notification = new NotificationEntity();
        notification.setSenderId(senderId);
        notification.setReceiverId(receiverId);
        notification.setReceiverType(0); // 个人
        notification.setTitle(title);
        notification.setContent(content);
        notification.setType(type);
        notification.setStatus(0);
        notification.setCreatedAt(new Date());
        
        // 保存到数据库
        notificationMapper.insert(notification);
        
        // 更新Redis中的未读计数
        updateUnreadCount(receiverId);
        
        // 发送到消息队列
        publishNotification(notification);
        
        log.info("发送个人通知成功: {} -> {}", senderId, receiverId);
    }
    
    /**
     * 发送系统公告（全体用户）
     */
    public void sendSystemAnnouncement(Long senderId, String title, String content) {
        NotificationEntity notification = new NotificationEntity();
        notification.setSenderId(senderId);
        notification.setReceiverId(0L); // 全体用户
        notification.setReceiverType(2); // 全体
        notification.setTitle(title);
        notification.setContent(content);
        notification.setType(0); // 系统公告
        notification.setStatus(0);
        notification.setCreatedAt(new Date());
        
        // 保存到数据库
        notificationMapper.insert(notification);
        
        // 发送到消息队列
        publishNotification(notification);
        
        log.info("发送系统公告成功: {}", title);
    }
    
    /**
     * 获取用户通知列表
     */
    public List<NotificationDTO> getUserNotifications(Long userId, int page, int size) {
        // 可以使用MyBatis Plus的分页插件
        List<NotificationDTO> notifications = notificationMapper.selectUserNotifications(userId);
        return notifications;
    }
    
    /**
     * 标记通知为已读
     */
    public void markAsRead(Long notificationId, Long userId) {
        // 更新通知状态
        NotificationEntity notification = notificationMapper.selectById(notificationId);
        if (notification != null) {
            if (notification.getReceiverType() == 2) {
                // 全体通知，更新notification_receiver表
                NotificationReceiverEntity receiver = new NotificationReceiverEntity();
                receiver.setNotificationId(notificationId);
                receiver.setReceiverId(userId);
                receiver.setStatus(1);
                receiver.setReadAt(new Date());
                receiver.setCreatedAt(new Date());
                receiverMapper.insert(receiver);
            } else {
                // 个人通知，直接更新notification表
                notification.setStatus(1);
                notification.setReadAt(new Date());
                notificationMapper.updateById(notification);
            }
            
            // 更新Redis中的未读计数
            updateUnreadCount(userId);
        }
    }
    
    /**
     * 获取用户未读通知数量
     */
    public int getUnreadCount(Long userId) {
        String key = UNREAD_COUNT_KEY + userId;
        Object count = redisTemplate.opsForValue().get(key);
        if (count == null) {
            // 从数据库查询并缓存
            int unreadCount = notificationMapper.countUnreadNotifications(userId);
            redisTemplate.opsForValue().set(key, unreadCount, Duration.ofMinutes(30));
            return unreadCount;
        }
        return (Integer) count;
    }
    
    /**
     * 更新Redis中的未读计数
     */
    private void updateUnreadCount(Long userId) {
        String key = UNREAD_COUNT_KEY + userId;
        int unreadCount = notificationMapper.countUnreadNotifications(userId);
        redisTemplate.opsForValue().set(key, unreadCount, Duration.ofMinutes(30));
    }
    
    /**
     * 发布通知到消息队列
     */
    private void publishNotification(NotificationEntity notification) {
        try {
            rabbitTemplate.convertAndSend(notificationExchange, notificationRoutingKey, notification);
        } catch (Exception e) {
            log.error("发布通知到消息队列失败", e);
        }
    }
}